﻿namespace LMT
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.ServiceProcess;
    using System.Threading;
    using System.Security.Principal;
    using System.Security;

    /// <summary>
    /// class used for win32 enviroment
    /// </summary>
    public abstract class Window
    {
        /// <summary>
        /// Send power command to window
        /// <param name="flag">value of power option</param>
        /// </summary>
        private static void DoCommand(int flag)
        {
            bool ok;
            Win32.TokPriv1Luid tp;

            // get current caller process
            IntPtr hproc = Win32.GetCurrentProcess();
            IntPtr htok = IntPtr.Zero;

            ok = Win32.OpenProcessToken(hproc, (int)Win32.Privileges.AdjustPrivilege | (int)Win32.Privileges.Querry, ref htok);
            tp.Count = 1;
            tp.Luid = 0;
            tp.Attr = (int)Win32.Privileges.PrivilegEnable;
            ok = Win32.LookupPrivilegeValue(null, Win32.SE_SHUTDOWN_NAME, ref tp.Luid);
            ok = Win32.AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
            ok = Win32.ExitWindowsEx(flag, 0);
        }

        /// <summary>
        /// reboot environment
        /// </summary>
        public static void Reboot()
        {
            Window.DoCommand((int)Win32.MachineTurnOff.Reboot + (int)Win32.MachineTurnOff.Force);
        }

        /// <summary>
        /// shut down environment
        /// </summary>
        public static void ShutDown()
        {
            Window.DoCommand((int)Win32.MachineTurnOff.Shutdown + (int)Win32.MachineTurnOff.Force);
        }

        /// <summary>
        /// log off environment
        /// </summary>
        public static void LogOff()
        {
            Window.DoCommand((int)Win32.MachineTurnOff.LogOff + (int)Win32.MachineTurnOff.Force);
        }

        /// <summary>
        /// lock environment
        /// </summary>
        public static void Lock()
        {
            Win32.LockWorkStation();
        }

        /// <summary>
        /// Checks if current logon user belong to administrator group
        /// </summary>
        /// <returns>If is elevated</returns>
        public static bool IsAdministrator()
        {
            WindowsIdentity id = WindowsIdentity.GetCurrent();
            WindowsPrincipal p = new WindowsPrincipal(id);
            return p.IsInRole(WindowsBuiltInRole.Administrator);
        }

        /// <summary>
        /// Stop window service by name
        /// </summary>
        /// <param name="serviceName"></param>
        /// <exception cref="System.InvalidOperationException"></exception>
        /// <exception cref="System.Win32Exception"></exception>
        public static void StopService(string serviceName)
        {
            ServiceController[] arraySrvCtrl;
            ServiceController TempSC = null;

            arraySrvCtrl = ServiceController.GetServices();
            foreach (ServiceController sc in arraySrvCtrl)
                if (sc.ServiceName.Equals(serviceName, StringComparison.OrdinalIgnoreCase))
                {
                    TempSC = sc;
                    break;
                }

            if (TempSC == null)
            {
                throw new ArgumentException(String.Format("Service {0} is not found", serviceName));
            }
            else
            {
                // If services is not stopped
                if (TempSC.Status != ServiceControllerStatus.Stopped)
                {
                    TempSC.Stop();
                    TempSC.Refresh();

                    while (TempSC.Status != ServiceControllerStatus.Stopped)
                    {
                        Thread.Sleep(15);
                        TempSC.Refresh();
                    }
                }
            }
        }
    }
}